package p.ithorns.tools.excel.write;

import cn.idev.excel.EasyExcel;
import cn.idev.excel.ExcelWriter;
import cn.idev.excel.write.builder.ExcelWriterSheetBuilder;
import cn.idev.excel.write.metadata.WriteSheet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import p.ithorns.tools.excel.AssistTools;
import p.ithorns.tools.excel.convert.Converters;
import p.ithorns.tools.excel.exception.ExportException;
import p.ithorns.tools.excel.model.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * MultiSheetExporter
 * 多Sheet页导出
 *
 * @author HtL
 * @date 2024/7/26 16:10
 * @since 1.0.0
 */
public class MultiSheetExporter {

    private final static Logger log = LoggerFactory.getLogger(MultiSheetExporter.class);

    /**
     * 设置响应
     *
     * @param response -
     * @param fileName -
     */
    public static void setResponse(HttpServletResponse response, String fileName) {
        // 设置响应信息
        // response.setContentType("application/vnd.ms-excel;charset=UTF-8");
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        String charset = StandardCharsets.UTF_8.name();
        response.setCharacterEncoding(charset);

        //设置导出文件名称（避免乱码）
        try {
            String name = URLEncoder.encode(fileName.concat(".xlsx"), charset);
            response.setHeader("Content-disposition", "attachment;filename=" + name);
        } catch (UnsupportedEncodingException e) {
            throw new ExportException(e.getMessage());
        }
    }

    /**
     * 导入模板
     *
     * @param fileName   -文件名
     * @param sheetBeans -sheet数据表
     */
    public static <T> void doExport(HttpServletResponse response, String fileName,
                                    Collection<? extends SheetDataBean> sheetBeans) throws IOException {
        // 默认文件名为表名
        // 设置响应信息
        setResponse(response, fileName);
        try (
                ServletOutputStream outputStream = response.getOutputStream();
                ExcelWriter writer = EasyExcel.write(outputStream)
                        // 不自动关闭流
                        .autoCloseStream(Boolean.FALSE).build();
        ) {
            for (SheetDataBean bean : sheetBeans) {
                // 构建sheet对象
                WriteSheet sheet = makeWriteSheet(bean);
                // 写出sheet数据
                writer.write(bean.getDataList(), sheet);
            }
            writer.finish();
        }
    }

    public static <T> void doExport(File file, Collection<? extends SheetDataBean> sheetBeans) throws IOException {
        try (
                OutputStream os = Files.newOutputStream(file.toPath());
                ExcelWriter writer = EasyExcel.write(os)
                        // 不自动关闭流
                        .autoCloseStream(Boolean.FALSE).build();
        ) {
            for (SheetDataBean bean : sheetBeans) {
                // 构建sheet对象
                WriteSheet sheet = makeWriteSheet(bean);
                // 写出sheet数据
                writer.write(bean.getDataList(), sheet);
            }
            writer.finish();
        }
    }

    /**
     * 构建sheet对象
     *
     * @param bean -SheetDataBean
     * @return WriteSheet
     */
    private static WriteSheet makeWriteSheet(SheetDataBean bean) {
        // 构建sheet对象
        ExcelWriterSheetBuilder sheetBuilder = EasyExcel.writerSheet(bean.getSheetName())
                .registerConverter(Converters.DATE_CONVERTER)
                .registerConverter(Converters.DATE_TIME_CONVERTER);

        if (bean instanceof SheetClassDataBean) {
            SheetClassDataBean classBean = (SheetClassDataBean) bean;
            sheetBuilder.head(classBean.headClass());
        } else if (bean instanceof SheetListDataBean) {
            SheetListDataBean listBean = (SheetListDataBean) bean;
            sheetBuilder.head(listBean.getHeadNames());
        } else {
            throw new ExportException("不支持的Sheet类型");
        }

        return sheetBuilder.build();
    }


    /**
     * 多Sheet导入错误文件
     *
     * @param importResult -导入结果
     * @throws IOException -
     */
    public static MultipartFile createErrorMultipartFile(final ImportMultiSheetResult importResult,
                                                         final File file) throws IOException {
        Assert.notNull(importResult, "导入结果为null");

        List<ImportSheetResult<?>> sheetResults = importResult.getImportSheetResults();
        List<SheetDataBean> sheetBeans = sheetResults.stream()
                .map(sheetResult -> {
                    String sheetName = sheetResult.getSheetName();
                    List<? extends RowError<?>> rowErrors = sheetResult.getRowErrors();
                    if (CollectionUtils.isEmpty(rowErrors)) {
                        log.info("[{}]->没有异常导入数据", sheetName);
                        return null;
                    }

                    Class<?> type = sheetResult.getType();
                    return AssistTools.makeErrSheetBean(sheetName, type, rowErrors);
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        // 导出数据到本地文件
        doExport(file, sheetBeans);

        // 转换成MultipartFile
        return AssistTools.createMultipartFile(file, "file");
    }

}